package org.zoomdev.zoom.dao.adapters.statement;

import org.zoomdev.zoom.common.caster.Caster;
import org.zoomdev.zoom.dao.adapters.StatementAdapter;

import java.sql.Blob;
import java.sql.Clob;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class StatementAdapters {


    static String2Clob STRING2CLOB = new String2Clob();
    static ByteArray2Blob BYTEARRAY2BLOB = new ByteArray2Blob();

    static StatementAdapter DEFAULT = new DefaultStateAdapter();


    static Map<String, StatementAdapter> pool = new ConcurrentHashMap<>();


    static String getKey(Class<?> fieldType, Class<?> columnType) {
        if (fieldType == null) {
            return columnType.getName();
        }
        return fieldType.getName() + "2" + columnType.getName();
    }

    /**
     * 获取一个从实体类到数据库的数据适配器
     *
     * @param fieldType  实体类字段类型
     * @param columnType 数据库字段类型
     * @return
     */
    public static StatementAdapter create(Class<?> fieldType, Class<?> columnType) {
        if (fieldType == null) {
            if (columnType == null) {
                return DEFAULT;
            }
            return create(columnType);
        }
        if (columnType == null) {
            return DEFAULT;
        }
        if (fieldType == columnType || columnType.isAssignableFrom(fieldType)) {
            return DEFAULT;
        }

        String key = getKey(fieldType, columnType);
        StatementAdapter adapter = pool.get(key);
        if (adapter == null) {
            if (Clob.class.isAssignableFrom(columnType)) {
                if (fieldType == String.class) {
                    adapter = STRING2CLOB;
                } else {
                    adapter = new CasterProxyStatementAdapter(Caster.wrap(fieldType, String.class), STRING2CLOB);
                }
            } else if (Blob.class.isAssignableFrom(columnType)) {
                if (fieldType == byte[].class) {
                    adapter = BYTEARRAY2BLOB;
                } else {
                    adapter = new CasterProxyStatementAdapter(Caster.wrap(fieldType, byte[].class), BYTEARRAY2BLOB);
                }
            } else {
                adapter = new CasterStatementAdapter(Caster.wrap(fieldType, columnType));
            }
            pool.putIfAbsent(key, adapter);
        }

        return adapter;
    }

    public static StatementAdapter create(Class<?> columnType) {
        String key = getKey(null, columnType);
        StatementAdapter adapter = pool.get(key);
        if (adapter == null) {
            if (Clob.class.isAssignableFrom(columnType)) {
                //先转成String
                adapter = new CasterProxyStatementAdapter(Caster.wrap(String.class), STRING2CLOB);
            } else if (Blob.class.isAssignableFrom(columnType)) {
                //先转成byte[]
                adapter = new CasterProxyStatementAdapter(Caster.wrap(byte[].class), BYTEARRAY2BLOB);
            } else {
                adapter = new CasterStatementAdapter(Caster.wrap(columnType));
            }
            pool.putIfAbsent(key, adapter);
        }

        return adapter;
    }
}
